﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;

using System;
using System.Collections.Generic;
using ttlang.compiler;
using ttlang.type.code;

namespace ttlang.type
{
    public enum DEFINETYPE
    {
        ERROR,
        PRIMITIVE,//原始類型 ,可以附加函數
        STRING,
        STRUCT,
        CLASS,
        NAMESPACE,
        DELEGATE,
    }

    public class TTType
    {
        public string[] modifers;//将来改成枚举
        public TTCode[] attributes;//

        Dictionary<string, TTType> _types;
        Dictionary<string, TTMethod> _methods;
        Dictionary<string, TTVar> _vars;
        List<string> _comments;

        //public Module? module;
        public DEFINETYPE definetype;
        //public string name = "";
        public bool unique;//唯一類型，別人不能用這個id


        public bool isNamespace
        {
            get
            {
                if (!isContainer)
                    throw new Exception("not isContainer");
                return definetype == DEFINETYPE.NAMESPACE;
                  
          
            }
        }
        public bool isContainer
        {
            get
            {
                return (definetype == DEFINETYPE.CLASS) || (definetype == DEFINETYPE.NAMESPACE) || (definetype == DEFINETYPE.STRUCT);
            }
        }
        public TTType(lib.Module module, TTType parent, string name, DEFINETYPE definetype, bool unique)
        {
            this.module = module;
            this.name = name;
            parentContainer = parent;
            this.definetype = definetype;
            this.unique = unique;
        }
        //public ContainerType type => ContainerType.Type;

        public string name
        {
            get;
            private set;
        }

        public string fullname
        {
            get
            {
                if (parentContainer != null && string.IsNullOrEmpty(parentContainer.fullname) == false)
                {
                    return parentContainer.fullname + "." + this.name;
                }
                else
                {
                    return this.name;
                }
            }
        }
        public lib.Module module
        {
            get;
            private set;
        }

        public TTType parentContainer
        {
            get;
            private set;
        }
        public IList<string> comments
        {
            get
            {
                return _comments;
            }
        }
        public void AddComment(string comment)
        {
            if (_comments == null)
                _comments = new List<string>();
            _comments.Add(comment);
        }

        public IReadOnlyDictionary<string, TTType> types
        {
            get
            {
                return _types;
            }
        }

        public IReadOnlyDictionary<string, TTMethod> methods
        {
            get
            {
                return _methods;
            }
        }

        public IReadOnlyDictionary<string, TTVar> vars
        {
            get
            {
                return _vars;
            }
        }


        public void AddMethod(TTMethod method)
        {
            if (this.definetype != DEFINETYPE.CLASS
                && this.definetype != DEFINETYPE.NAMESPACE
                && this.definetype != DEFINETYPE.STRUCT
                && this.definetype != DEFINETYPE.PRIMITIVE//原型类可以有函数
                && this.definetype != DEFINETYPE.STRING
                )
                throw new NotSupportedException("only calss can AddMethod.");

            if (this._methods == null)
                this._methods = new Dictionary<string, TTMethod>();

            this._methods.Add(method.name, method);
        }

        public void AddType(TTType type)
        {
            //if (this.definetype != DEFINETYPE.CLASS)
            //    throw new NotSupportedException("only class can AddType.");

            if (this._types == null)
                this._types = new Dictionary<string, TTType>();

            this._types.Add(type.name, type);
        }

        public void AddVar(TTVar var)
        {
            if (this.definetype != DEFINETYPE.CLASS && this.definetype != DEFINETYPE.NAMESPACE && this.definetype != DEFINETYPE.STRUCT
                && this.definetype != DEFINETYPE.PRIMITIVE//原型类可以有静态成员
                )
                throw new NotSupportedException("only calss can AddType.");

            if (this._vars == null)
                this._vars = new Dictionary<string, TTVar>();

            this._vars.Add(var.name, var);
        }

        public override string ToString()
        {
            //临时处理，将来会返回全名
            throw new NotSupportedException("use name or fullname.");
        }
        public bool FindMethod(string id, out TTMethod method)
        {
            method = null;
            if (this._methods == null)
                return false;
            return this._methods.TryGetValue(id, out method);
        }
        public bool FindVar(string id, out TTVar var)
        {
            var = null;
            if (this._vars == null)
                return false;
            return this._vars.TryGetValue(id, out var);
        }
        public bool FindType(string id, out TTType type)
        {
            type = null;
            if (this.types == null)
                return false;
            return this.types.TryGetValue(id, out type);
        }
        public bool FindMember(string id, out IMember member)
        {
            if (FindMethod(id, out var _m))
            {
                member = _m;
                return true;
            }
            else if (FindVar(id, out var _v))
            {
                member = _v;
                return true;
            }
            else
            {
                member = null;
                return false;
            }
        }
        public bool FindSubContainer(string id, out TTType container)
        {
            var b = FindType(id, out var _v);
            container = _v;
            return b;
        }

    }

}
